<!--
Copyright (c) Facebook, Inc. and its affiliates. All rights reserved.

This file provided by Facebook is for non-commercial testing and evaluation
purposes only. Facebook reserves all rights not expressly granted.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-->
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Draft • Link Editor</title>
    <link rel="stylesheet" href="../../../dist/Draft.css" />
  </head>
  <body>
    <div id="target"></div>
    <script src="../../../node_modules/react/umd/react.development.js"></script>
    <script src="../../../node_modules/react-dom/umd/react-dom.development.js"></script>
    <script src="../../../node_modules/immutable/dist/immutable.js"></script>
    <script src="../../../node_modules/es6-shim/es6-shim.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-core/5.8.34/browser.js"></script>
    <script src="../../../dist/Draft.js"></script>
    <script type="text/babel">
      'use strict';

      const {
        convertToRaw,
        CompositeDecorator,
        Editor,
        EditorState,
        RichUtils,
      } = Draft;

      class LinkEditorExample extends React.Component {
        constructor(props) {
          super(props);

          const decorator = new CompositeDecorator([
            {
              strategy: findLinkEntities,
              component: Link,
            },
          ]);

          this.state = {
            editorState: EditorState.createEmpty(decorator),
            showURLInput: false,
            urlValue: '',
          };

          this.focus = () => this.refs.editor.focus();
          this.onChange = (editorState) => this.setState({editorState});
          this.logState = () => {
            const content = this.state.editorState.getCurrentContent();
            console.log(convertToRaw(content));
          };

          this.promptForLink = this._promptForLink.bind(this);
          this.onURLChange = (e) => this.setState({urlValue: e.target.value});
          this.confirmLink = this._confirmLink.bind(this);
          this.onLinkInputKeyDown = this._onLinkInputKeyDown.bind(this);
          this.removeLink = this._removeLink.bind(this);
        }

        _promptForLink(e) {
          e.preventDefault();
          const {editorState} = this.state;
          const selection = editorState.getSelection();
          if (!selection.isCollapsed()) {
            const contentState = editorState.getCurrentContent();
            const startKey = editorState.getSelection().getStartKey();
            const startOffset = editorState.getSelection().getStartOffset();
            const blockWithLinkAtBeginning = contentState.getBlockForKey(startKey);
            const linkKey = blockWithLinkAtBeginning.getEntityAt(startOffset);

            let url = '';
            if (linkKey) {
              const linkInstance = contentState.getEntity(linkKey);
              url = linkInstance.getData().url;
            }

            this.setState({
              showURLInput: true,
              urlValue: url,
            }, () => {
              setTimeout(() => this.refs.url.focus(), 0);
            });
          }
        }

        _confirmLink(e) {
          e.preventDefault();
          const {editorState, urlValue} = this.state;
          const contentState = editorState.getCurrentContent();
          const contentStateWithEntity = contentState.createEntity(
            'LINK',
            'MUTABLE',
            {url: urlValue}
          );
          const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
          const newEditorState = EditorState.set(editorState, { currentContent: contentStateWithEntity });
          this.setState({
            editorState: RichUtils.toggleLink(
              newEditorState,
              newEditorState.getSelection(),
              entityKey
            ),
            showURLInput: false,
            urlValue: '',
          }, () => {
            setTimeout(() => this.refs.editor.focus(), 0);
          });
        }

        _onLinkInputKeyDown(e) {
          if (e.which === 13) {
            this._confirmLink(e);
          }
        }

        _removeLink(e) {
          e.preventDefault();
          const {editorState} = this.state;
          const selection = editorState.getSelection();
          if (!selection.isCollapsed()) {
            this.setState({
              editorState: RichUtils.toggleLink(editorState, selection, null),
            });
          }
        }

        render() {
          let urlInput;
          if (this.state.showURLInput) {
            urlInput =
              <div style={styles.urlInputContainer}>
                <input
                  onChange={this.onURLChange}
                  ref="url"
                  style={styles.urlInput}
                  type="text"
                  value={this.state.urlValue}
                  onKeyDown={this.onLinkInputKeyDown}
                />
                <button onMouseDown={this.confirmLink}>
                  Confirm
                </button>
              </div>;
          }

          return (
            <div style={styles.root}>
              <div style={{marginBottom: 10}}>
                Select some text, then use the buttons to add or remove links
                on the selected text.
              </div>
              <div style={styles.buttons}>
                <button
                  onMouseDown={this.promptForLink}
                  style={{marginRight: 10}}>
                  Add Link
                </button>
                <button onMouseDown={this.removeLink}>
                  Remove Link
                </button>
              </div>
              {urlInput}
              <div style={styles.editor} onClick={this.focus}>
                <Editor
                  editorState={this.state.editorState}
                  onChange={this.onChange}
                  placeholder="Enter some text..."
                  ref="editor"
                />
              </div>
              <input
                onClick={this.logState}
                style={styles.button}
                type="button"
                value="Log State"
              />
            </div>
          );
        }
      }

      function findLinkEntities(contentBlock, callback, contentState) {
        contentBlock.findEntityRanges(
          (character) => {
            const entityKey = character.getEntity();
            return (
              entityKey !== null &&
              contentState.getEntity(entityKey).getType() === 'LINK'
            );
          },
          callback
        );
      }

      const Link = (props) => {
        const {url} = props.contentState.getEntity(props.entityKey).getData();
        return (
          <a href={url} style={styles.link}>
            {props.children}
          </a>
        );
      };

      const styles = {
        root: {
          fontFamily: '\'Georgia\', serif',
          padding: 20,
          width: 600,
        },
        buttons: {
          marginBottom: 10,
        },
        urlInputContainer: {
          marginBottom: 10,
        },
        urlInput: {
          fontFamily: '\'Georgia\', serif',
          marginRight: 10,
          padding: 3,
        },
        editor: {
          border: '1px solid #ccc',
          cursor: 'text',
          minHeight: 80,
          padding: 10,
        },
        button: {
          marginTop: 10,
          textAlign: 'center',
        },
        link: {
          color: '#3b5998',
          textDecoration: 'underline',
        },
      };

      ReactDOM.render(
        <LinkEditorExample />,
        document.getElementById('target')
      );
    </script>
  </body>
</html>
